// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: donggu

#pragma once

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "coin2/base/request/session_pool.h"
#include "coin2/exchange/base/order/control/control_handler.h"
#include "coin2/exchange/base/order/external.h"
#include "coin2/exchange/base/order/processor.h"
#include "coin2/exchange/base/order/stats/stats_manager.h"
#include "coin2/exchange/base/order/update_manager.h"
#include "coin2/exchange/base/symbology/product_holder_manager.h"

namespace {

using MethodsVector = std::vector<std::pair<
    std::string,
    std::map<std::string, std::function<std::string(const std::string&)>>>>;
}
namespace coin2::exchange::base::order {

namespace impl {

using coin2::exchange::order::OrderManagerConfig;
using coin2::exchange::order::OrderSystemType;
using RttInfo = coin2::base::request::RttInfo;

class OrderSystemManager : public ControlHandler::Callback,
                           public StatsManager::Callback {
 public:
  explicit OrderSystemManager(
      const di::ConstantInjection& ci, const OrderManagerConfig& config,
      LiveAsyncExecutor* live_executor, ArchiveSyncExecutor* archive_executor,
      coin2::exchange::base::symbology::ProductHolderManager* phm,
      coin2::feed::mgr::FeedSubsystemManager* fss, IOrderSubscriber* strategy,
      const std::string& strategy_name);

  BaseOrderSubsystem* GetUniqueSystemByName(const std::string& system_name);
  const std::vector<std::unique_ptr<BaseOrderSubsystem>>& GetAllSystems() {
    return systems_;
  }

  // TODO(xguo) Make it better. Return the subsystem.
  BaseOrderSubsystem* GetUniqueSystem(const MarketExchangeApi& mea);

  std::vector<const IProduct*> GetProducts() const;

  void DebugPrint() const;

  void GetHealthReport(int indent, std::string* report) const;

  MethodsVector ExportMethods();

 private:
  // inherit from ControlHandler::Callback
  void OnEvent(ControlType uri) override;

  // inherit from StatsManager::Callback
  void OnGenricReport() override;

 private:
  const OrderManagerConfig config_;
  LiveAsyncExecutor* live_executor_;
  ArchiveSyncExecutor* archive_executor_;
  std::vector<std::unique_ptr<BaseOrderSubsystem>> systems_;
  coin2::exchange::base::symbology::ProductHolderManager*
      product_holder_manager_;
  std::unique_ptr<ControlHandler> control_handler_;
  std::unique_ptr<StatsManager> stats_manager_;
};
}  // namespace impl

using impl::OrderSystemManager;

}  // namespace coin2::exchange::base::order
